/*
 * MediaSourceT.h
 *
 *  Created on: 2015年12月31日
 *      Author: terry
 */

#ifndef SRC_MEDIASOURCETEX_H_
#define SRC_MEDIASOURCETEX_H_

#include "MediaSinkArray.h"

namespace av
{

template < class T >
class MediaSourceExT : public T
{
public:
    MediaSourceExT():
		m_state(STATE_STOPPED)
	{
	}

	virtual ~MediaSourceExT()
	{

	}

	virtual std::string getUrl()
	{
		return m_url;
	}

	virtual bool getMediaFormat(MediaFormat& fmt)
	{
		if (!m_format.isValid())
		{
			return false;
		}

		fmt = m_format;
		return true;
	}

	virtual int startStream()
	{
		setState(STATE_PLAYING);
		return 0;
	}

	virtual int pauseStream()
	{
		setState(STATE_PAUSED);
		return 0;
	}

	virtual void stopStream()
	{
		setState(STATE_STOPPED);
	}

	void setState(StreamState state)
	{
		comn::AutoCritSec lock(m_cs);
		m_state = state;
	}

	virtual int getState()
	{
		return m_state;
	}

	virtual int addSink(MediaSinkPtr pSink)
	{
		int rc = m_arrSink.addSink(pSink);
		if (rc == 0)
		{
			if (m_format.isValid())
			{
				pSink->onMediaFormat(m_format);
			}
		}
		return rc;
	}

	virtual void removeSink(MediaSinkPtr pSink)
	{
		m_arrSink.removeSink(pSink);
	}

	virtual void removeSinks()
	{
		m_arrSink.removeSinks();
	}

	virtual size_t getSinkCount()
	{
		return m_arrSink.getSinkCount();
	}

	virtual int forceKeyFrame()
	{
		return ENOSYS;
	}

//	virtual bool isMediaFormatReady()
//	{
//		return m_format.isValid();
//	}

protected:
	virtual void fireMediaFormat(const MediaFormat& fmt)
	{
		m_arrSink.fireMediaFormat(fmt);
	}

	virtual void fireMediaPacket(MediaPacketPtr& pkt)
	{
		m_arrSink.fireMediaPacket(pkt);
	}

	virtual void fireMediaEvent(int event)
	{
		m_arrSink.fireMediaEvent(event);
	}


protected:
	comn::CriticalSection m_cs;
	std::string m_url;
	MediaFormat	m_format;
	StreamState	m_state;
	MediaSinkArray	m_arrSink;


};


} /* namespace av */

#endif /* SRC_MEDIASOURCETEX_H_ */
